<?php
/**
 * Base class for objects that run complex database queries (user and content)
 *
 * @package Concerto
 * @subpackge Models
 * @author Jason Raede <jason@torchdm.com>
 */
namespace application\models;
use \application\utilities\Utility as Utility;
class ContentBase {
	
	/**
	 * Array of all database columns returned in the query.
	 *
	 * @var array
	 */
	protected $dbFields = array();
	
	/**
	 * Array of data formatted by the object's data types.
	 *
	 * This is essentially the object's database fields formatted in order to be used
	 * in a form and in the displayField/getField functions. Sometimes it may be
	 * one field to one key/value pair, sometimes it may be one to three, and sometimes it may
	 * be three to one. Really depends on the data type.
	 *
	 * @var array
	 */
	public $data = array();
	
	/**
	 * The content fields associated with this object
	 *
	 * @var array
	 */
	protected $fields = array();
	
	/**
	 * @deprecated
	 */
	public $fieldColumns = array();
	
	/**
	 * The Form object that will render this object's add/edit form
	 *
	 * @var \application\models\Form
	 */
	public $form;
	
	/**
	 * Messages returned by actions performed on or by this object
	 *
	 * @var array
	 */
	public $messages = array(
		'success'=>array(),
		'error'=>array(),
		'alert'=>array()
	);
	
	/**
	 * Any property set on this object will go into its dbFields property
	 */
	public function __get($var) {
		return $this->dbFields[$var];
	}
	
	/**
	 * Any property set on this object will go into its dbFields property
	 */
	public function __set($var, $value) {
		$this->dbFields[$var] = $value;
	}
	
	/**
	 * Return data according to a property
	 *
	 * @param string $property
	 * @return mixed The data
	 */
	public function getData($property) {
		return $this->data[$property];
	}
	
	/**
	 * Set a data property
	 *
	 * @param string $property
	 * @param mixed $value
	 */
	public function setData($property, $value) {
		$this->data[$property] = $value;
	}
	
	/**
	 * Returns the untampered value of a database column
	 *
	 * @param string $column
	 * @return mixed The column's value
	 */
	public function getDBField($column) {
		return $this->dbFields[$column];
	}
	
	/**
	 * Sets the value of a database column. Used immediately before updating
	 * or inserting in the database
	 *
	 * @param string $column The column
	 * @param mixed $value The value to set it to
	 * @param string $subarray The name of the table the data goes into.
	 */
	public function setDBField($column, $value, $subarray = null) {
		if($subarray) {
			$this->dbFields[$subarray][$column] = $value;
		}
		else {
			$this->dbFields[$column] = $value;
		}
	}
	
	/**
	 * Create a form object with certain fields
	 *
	 * @param string/array $fields		Optionally specify fields to display. If this is a string, 
	 *									we grab fields from predefined form definitions. If array, 
	 *									load fields specified.
	 */
	public function initForm($fields = null) {
		if(is_array($fields)) {
			// Convert to array of form field db objects
			$fieldObjects = array();
			foreach($form as $fieldName) {
				$field = $this->fields[$fieldName];
				if($field) $fieldObjects[$fieldName] = $field;
				else Utility::triggerError('Unrecognized field name.');
			}
		}
		else if($this->forms[$fields]) {
			
			$fieldObjects = $this->forms[$fields];
		}
		else {
			// Init the form with all fields
			$fieldObjects = $this->fields;
		}
		
		$this->form = new \application\models\Form($fieldObjects, $this);
	}
	
	/**
	 * Helper function for validating the form's data
	 * 
	 * @see \application\models\Form::validate()
	 */
	public function validateForm() {
		$this->form->validate();
	}
	
	/**
	 * Helper function for displaying the form's header
	 *
	 * @see \application\models\Form::header()
	 */
	public function formHeader() {
		$this->form->header();
	}
	
	
	/**
	 * Gets data from the form by going through all data associated with the object,
	 * then checking if any data of the same name was sent by the form. Don't worry,
	 * this is only run after all form data has been validated
	 */
	protected function getFormData() {
		foreach($this->data as $field=>$value) {
			if($input = $_REQUEST[$field]) {
				if(is_array($input)) {
					$this->data[$field] = Utility::arrayFunction($input, 'stripslashes');
				}
				else {
					$this->data[$field] = stripslashes($input);
				}
			}
		}
	}
	
	/**
	 * @deprecated
	 */
	public function displayForm() {
		
	}
	
	/**
	 * The data type combines or splits data when going into the database, so we do the
	 * opposite when coming out of the database
	 *
	 * @param object $field The stdClass object representing the row from cn_content_fields
	 * @see \application\datatypes\DataType::fromDB()
	 */
	protected function fromDB($field) {
		$class = 'application\\datatypes\\' . $field->cf_data_type;
		$this->data = array_merge($this->data, $class::fromDB($this->dbFields, $field, $this->data));
	}
	
	
	
	/**
	 * Prepare an object's data for display
	 *
	 * @param string $field The field's exact display name
	 * @param array $params Optional display parameters to pass to the datatype
	 * @see \application\datatypes\DataType::prepareData()
	 * @return mixed The data returned by the datatype's prepareData() method
	 */
	public function prepareData($field, $params = null) {
		$column = $this->fields[$field]->cf_column;
		$dataType = $this->fields[$field]->cf_data_type;
		$class = 'application\\datatypes\\' . $dataType;
		
		if(file_exists(CN_APPLICATION_PATH.'application/datatypes/'.$dataType.'.php') || Modulator()->getDataTypePath($dataType)) {
			$display = $class::prepareData($this->fields[$field], $this->data, $params);
			return $display;
		}
		else {
			return 'Error: Unrecognized field name.';
		}
		
	}
}
?>